#!/usr/bin/env python
#-*-coding:utf-8-*-
# ---------------------------------
# create-time:      <2009/04/01 05:08:09>
# last-update-time: <halida 04/01/2009 16:10:11>
# ---------------------------------
# test for create tree view for class Entity 
# ---------------------------------
# todo
# auto create tree
# edit tree item

from qtlib import *

import pickle

class Entity():
    def __init__(self,name,desc,parent=None):
        self.name=name
        self.desc=desc
        self.parent=parent

class EntityTreeItem:
    def __init__(self, entity, root , parent=None):
        self.parentItem = parent
        self.entity = entity
        self.root = root
        self.childItems = []
    
    def setParent(self,parent):
        self.parentItem = parent        

    def appendChild(self, item):
        self.childItems.append(item)

    def removeChild(self,item):
        print self.childItems,item
        self.childItems.remove(item)

    def child(self, row):
        return self.childItems[row]

    def childCount(self):
        return len(self.childItems)

    def columnCount(self):
        return self.root.columnCount()

    def data(self, column):
        return self.root.getColumn(column,self.entity)

    def setData(self,column,value):
        self.root.setColumn(column,self.entity,value)

    def parent(self):
        return self.parentItem

    def row(self):
        if self.parentItem:
            return self.parentItem.childItems.index(self)
        return 0
    ##################################
    @staticmethod
    def createTree(elist,root):
        treelist = dict(
            map(lambda e:(e,EntityTreeItem(e,root)),
                elist))
        for e in elist:
            if e.parent:
                treelist[e].setParent(
                    treelist[e.parent]
                    )
                treelist[e.parent].appendChild(
                    treelist[e]
                    )
            else:
                treelist[e].setParent(root)
                root.appendChild(treelist[e])

class EntityRootItem(EntityTreeItem):
    displayer = (
        ('Name','name'),
        ('Desc','desc'),
        )

    def __init__(self):
        self.parentItem = None
        self.childItems = []

    def data(self, column):
        return self.displayer[column][0]

    def getColumn(self,column,entity):
        return getattr(entity,self.displayer[column][1])

    def setColumn(self,column,entity,value):
        return setattr(entity,self.displayer[column][1],value)        

    def columnCount(self):
        return len(self.displayer)

class TreeModel(QAbstractItemModel):
    def __init__(self,rootItem,parent=None):
        QAbstractItemModel.__init__(self, parent)
        self.rootItem = rootItem

    def columnCount(self, parent):
        if parent.isValid():
            return parent.internalPointer().columnCount()
        else:
            return self.rootItem.columnCount()

    def data(self, index, role):
        if not index.isValid():
            return QVariant()

        if role != Qt.DisplayRole:
            return QVariant()

        item = index.internalPointer()
        
        return QVariant(item.data(index.column()))

    def flags(self, index):
        if not index.isValid():
            return Qt.ItemIsEnabled

        return Qt.ItemIsEnabled | Qt.ItemIsSelectable |\
            Qt.ItemIsDragEnabled | Qt.ItemIsDropEnabled |\
            Qt.ItemIsEditable

    def headerData(self, section, orientation, role):
        if orientation == Qt.Horizontal \
                and role == Qt.DisplayRole:
            return QVariant(self.rootItem.data(section))

        return QVariant()

    def index(self, row, column, parent):
        if row < 0 or column < 0 or row >= self.rowCount(parent) or column >= self.columnCount(parent):
            return QModelIndex()

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        childItem = parentItem.child(row)
        if childItem:
            return self.createIndex(row, column, childItem)
        else:
            return QModelIndex()

    def parent(self, index):
        if not index.isValid():
            return QModelIndex()

        childItem = index.internalPointer()
        parentItem = childItem.parent()

        if parentItem == self.rootItem:
            return QModelIndex()

        return self.createIndex(parentItem.row(), 0, parentItem)

    def rowCount(self, parent):
        if parent.column() > 0:
            return 0

        if not parent.isValid():
            parentItem = self.rootItem
        else:
            parentItem = parent.internalPointer()

        return parentItem.childCount()

    #edit
    def setData(self,index,value,role):
        logging.debug('edit data')
        if index.isValid() and role == Qt.EditRole:
            item = index.internalPointer()
            item.setData(index.column(),value.toString())
            emit(self,"dataChanged(index, index)",index,index)
            return True
        return False

    #drag and drop
    MIME_TYPE = "application/entity-tree-item"
    def supportedDragActions(self):
        return Qt.MoveAction

    def mimeTypes(self):
        types = QStringList(self.MIME_TYPE)
        return types

    def mimeData(self,indexes):
        #get indexs
        items = set()
        for index in indexes:
            if index.isValid():
                item = index.internalPointer()
                items.add(item)
        #save
        ba = QByteArray()
        ba.append(pickle.dumps(items))
        mimeData = QMimeData()
        mimeData.setData(self.MIME_TYPE, ba)
        #delete item
        #todo
        return mimeData

    def dropMimeData(self,data,action,row,column,parent):
        if action == Qt.IgnoreAction:
            return True

        if not data.hasFormat(self.MIME_TYPE):
            return False

        if (column > 0):
            return False

        #chage parents:
        logging.debug("accept mime data")
        #get from index
        items = pickle.loads(data.data(self.MIME_TYPE).data())
        #add index
        parentItem = parent.internalPointer()
        for item in items:
            parentItem.appendChild(item)
            item.parent().removeChild(item)
            item.setParent(parentItem)
        emit(self,"dataChanged(index, index)",parent,parent)
        return True

def create_entity_list():
    e1 = Entity("work","working")
    e2 = Entity("study","studying")
    e3 = Entity("pts","ppp",e1)
    e4 = Entity("spi","sss",e3)
    return set((e1,e2,e3,e4))


def testData2():
    elist = create_entity_list()
    root = EntityRootItem()
    EntityTreeItem.createTree(elist,root)

    #e2 = Entity("study","studying")
    #child = EntityTreeItem(e2,root,root)
    #root.appendChild(child)
    return root

if __name__ == "__main__":
    model = TreeModel(testData2())

    view = QTreeView()
    view.setModel(model)
    view.setDragEnabled(True)
    view.setDropIndicatorShown(True)
    view.viewport().setAcceptDrops(True)
    view.setWindowTitle("Simple Tree Model")
    view.show()
    run()

